package hyPeerDriveTests;

import static org.junit.Assert.*;

import java.util.Iterator;

import org.junit.Test;

import phase4Specification.testing.DepositBroadcastVisitor;
import dbPhase.hypeerweb.BroadcastVisitor;
import dbPhase.hypeerweb.HyPeerWeb;
import dbPhase.hypeerweb.Node;
import dbPhase.hypeerweb.Parameters;

public class BrentTests {

	/*
	 * Testing Broadcast
	 * 
	 * 
	 * Equivalence partitioning
	 * 
	 * Equivalence in size of hypeerweb when broadcasting
	 * 1. Empty hypeerweb
	 * 2. Hypeerweb of size 1
	 * 3. Hypeerweb of size 2, 4, 8, 16, 32 (Cap)
	 * 4. Hypeerweb of size between 3 and 31
	 * 
	 */
	@Test
	public void test() {
		
		// Hypeerweb of size 1
		assertTrue(broadcast(0,1));
		
		// Perfect Hypeerwebs
		assertTrue(broadcast(0,2));
		assertTrue(broadcast(0,4));
		assertTrue(broadcast(0,8));
		assertTrue(broadcast(0,16));
		assertTrue(broadcast(0,32));
		
		// Border Cases
		assertTrue(broadcast(0,3));
		assertTrue(broadcast(0,5));
		assertTrue(broadcast(0,7));
		assertTrue(broadcast(0,9));
		assertTrue(broadcast(0,15));
		assertTrue(broadcast(0,17));
		assertTrue(broadcast(0,31));
		
		// Empty Hypeerweb
		assertTrue(broadcastBadNode(0,0));
		
		Parameters p = BroadcastVisitor.createInitialParameters();
		p.set("Source", null);
		DepositBroadcastVisitor db = new DepositBroadcastVisitor();
		db.visit(new Node(0), p);
	}

	public void createHyPeerWebWithSize(HyPeerWeb hp, int size) {
		hp.clear();
		Node n0 = new Node(0);
		hp.addToHyPeerWeb(n0, null);
		for(int i = 1; i < size; i++) {
			hp.addToHyPeerWeb(new Node(0), n0);
		}
	}
	
	public boolean allNodesHaveMessage(HyPeerWeb hp) {
		Iterator<Node> nodes = hp.iterator();
		while(nodes.hasNext()) {
			Node n = nodes.next();
			if(!n.getContents().get(DepositBroadcastVisitor.DEPOSIT_KEY).equals("Hello!")) {
				return false;
			}
		}
		return true;
	}
	
	public boolean broadcast(int startNode, int size) {
		HyPeerWeb hp = HyPeerWeb.getSingleton();
		createHyPeerWebWithSize(hp, size);
		DepositBroadcastVisitor db = new DepositBroadcastVisitor();
		Parameters p = BroadcastVisitor.createInitialParameters();
		p.containsKey("try");
		p.set(DepositBroadcastVisitor.DEPOSIT_KEY, "Hello!");
		
		Node n = hp.getNode(startNode);
		db.visit(n, p);
		
		return allNodesHaveMessage(hp);
	}
	
	public boolean noNodesHaveMessage(HyPeerWeb hp) {
		Iterator<Node> nodes = hp.iterator();
		while(nodes.hasNext()) {
			Node n = nodes.next();
			if(n.getContents().containsKey(DepositBroadcastVisitor.DEPOSIT_KEY)) {
				return false;
			}
		}
		return true;
	}
	
	public boolean broadcastBadNode(int startNode, int size) {
		HyPeerWeb hp = HyPeerWeb.getSingleton();
		createHyPeerWebWithSize(hp, size);
		DepositBroadcastVisitor db = new DepositBroadcastVisitor();
		Parameters p = BroadcastVisitor.createInitialParameters();
		p.set(DepositBroadcastVisitor.DEPOSIT_KEY, "Hello!");
		
		Node n = new Node(startNode);
		db.visit(n, p);
		
		return noNodesHaveMessage(hp);
	}
}
